home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
JCSM Shareware Collection 1993 November
/
JCSM Shareware Collection - 1993-11.iso
/
cl720
/
s3bas11.lzh
/
PORT.BAS
< prev
next >
Wrap
BASIC Source File
|
1993-05-02
|
8KB
|
229 lines
'Example of using the word functions that are in the
'WORD.BAS file to manipulate the I/O ports.
'
'By: George Spafford Copyright 1993
'
'No additional libraries required
'
'v1.0 05/02/93
'
'**************************************************
'If you use these routines, please have the courtesy
'of registering the tutorial.
'Make sure that you have all of your variables typed
'correctly before you use one of the following
'routines. Use integers where integers are identified (%).
'Use long integers where long integers are identified (&).
'Int2Long& is a function that accepts a signed
'integer and returns an unsigned long integer. Since
'BASIC uses the high bit to toggle the sign of an
'integer, you must convert it to a long integer before
'you perform any bit operations on it.
DECLARE FUNCTION Int2Long& (IntNumber%)
'BASIC does NOT have a built in facility to PEEK
'words! Tell the PeekWord% function where to look,
'and it will read in a word at that segment and offset.
DECLARE FUNCTION PeekWord% (Segment%, Offset%)
'As with Peeks, BASIC does not support a POKE function
'for words. This next subroutine adds that capability.
'Tell the subroutine the segment, offset and word that
'you wish it to POKE in and it will do so.
DECLARE SUB PokeWord (Segment%, Offset%, Word%)
'As you code more and more programs, try to make your code
'as modular as possible. By creating objects (OOP systems),
'you can significantly increase your code reusability.
'Try to only create the wheel once! Some of the demos would
'benefit greatly by judicial use of subroutines. In order to
'have top-down readability, I did not modularize the code.
'Just a FYI -- George
DEFINT A-Z
Title$ = "S3 Demo of WORD functions and I/O ports Copyright George Spafford 1993"
Main:
CLS
PRINT Title$
LOCATE 3, 30: PRINT "To enter hexadecimal numbers, prefix your answer"
LOCATE 4, 30: PRINT "with &H. For example, &H400 represents 400 Hex."
LOCATE 3, 1
GOSUB ReadPorts
PRINT "Menu Port Address"
PRINT "---- ---- -------"
PRINT " 1. COM1: "; HEX$(COM1); " Hex" 'HEX$ formats numeric
PRINT " 2. COM2: "; HEX$(COM2) 'input to a hexadecimal
PRINT " 3. COM3: "; HEX$(COM3) 'string representation
PRINT " 4. COM4: "; HEX$(COM4)
PRINT " 5. LPT1: "; HEX$(LPT1)
PRINT " 6. LPT2: "; HEX$(LPT2)
PRINT " 7. LPT3: "; HEX$(LPT3)
PRINT " 8. LPT4: "; HEX$(LPT4)
PRINT "======================="
PRINT
PRINT "Please select an option:"
PRINT
INPUT "(D)elete (E)dit (S)wap (Q)uit: ", Ans$
Ans$ = LTRIM$(RTRIM$(UCASE$(Ans$))) 'trim spaces and make the
'answer upper case.
IF Ans$ = "" THEN PRINT : PRINT : END 'if answer is NULL then end
'Just a note regarding efficiency when conditions are involved:
'If you have more than a couple of repetitive tasks to test, use
'the SELECT CASE method. IF THEN statements require converting and
'testing a condition each time. A select only has to convert the test
'variable once and then evaluate it against all of the answers.
'Taking this approach one step further, if you can use integer varaibles,
'then the test is even faster. In the instance below, speed is not a
'factor, readability is.
SELECT CASE Ans$
CASE "D"
PRINT
INPUT "Delete which port: ", Del$
Del$ = LTRIM$(RTRIM$(Del$))
IF Del$ <> "" THEN
Value = VAL(Del$)
GOSUB Choice
IF Offset <> 0 THEN
CALL PokeWord(0, Offset, 0)
END IF
END IF
CASE "E"
PRINT
INPUT "Edit which port: ", Edit$
Edit$ = LTRIM$(RTRIM$(Edit$))
IF Edit$ <> "" THEN
PRINT
Value = VAL(Edit$)
GOSUB Choice
IF Offset <> 0 THEN
INPUT "New value: ", NewValue
CALL PokeWord(0, Offset, NewValue)
END IF
END IF
CASE "S"
PRINT
INPUT "Swap port one: ", From$
Value = VAL(From$)
GOSUB Choice
FromAddr = Addr
FromOffset = Offset
INPUT "Swap port two: ", To$
Value = VAL(To$)
GOSUB Choice
ToAddr = Addr
ToOffset = Offset
IF ToOffset <> 0 AND FromOffset <> 0 THEN
CALL PokeWord(0, ToOffset, FromAddr)
CALL PokeWord(0, FromOffset, ToAddr)
END IF
CASE "Q"
PRINT : PRINT : END
END SELECT
GOTO Main
END
Choice:
Addr = 0
SELECT CASE Value
CASE 1
Addr = COM1
Offset = COM1off
CASE 2
Addr = COM2
Offset = COM2off
CASE 3
Addr = COM3
Offset = COM3off
CASE 4
Addr = COM4
Offset = COM4off
CASE 5
Addr = LPT1
Offset = LPT1off
CASE 6
Addr = LPT2
Offset = LPT2off
CASE 7
Addr = LPT3
Offset = LPT3off
CASE 8
Addr = LPT4
Offset = LPT4off
CASE ELSE
Addr = 0
Offset = 0
END SELECT
ReadPorts:
'The BIOS data area starts at 0000:0400. The first
'16 bytes of it concerns the I/O ports. If the port
'is enabled, there will be a word entry that describes
'the I/O address where data should be sent when that device
'is used. If the word is 0, then the device has not been
'recognized. If a value is forced, then the system will
'recognize that port whether it truly exists or not.
'For example, some systems do not automatically scan
'for COM3 and COM4 at POST (Power On Self-Test) time. You
'must enter the address manually for that port if you
'need to use it in those instances.
COM1off = &H400 'Save Offset
COM1 = PeekWord%(0, COM1off) 'Get I/O address used
COM2off = &H402
COM2 = PeekWord%(0, COM2off)
COM3off = &H404
COM3 = PeekWord%(0, COM3off)
COM4off = &H406
COM4 = PeekWord%(0, COM4off)
LPT1off = &H408
LPT1 = PeekWord%(0, LPT1off)
LPT2off = &H40A
LPT2 = PeekWord%(0, LPT2off)
LPT3off = &H40C
LPT3 = PeekWord%(0, LPT3off)
LPT4off = &H40E
LPT4 = PeekWord%(0, LPT4off)
RETURN
DEFSNG A-Z
FUNCTION Int2Long& (IntNumber%)
'If the integer is negative, we need to add 65536
'to the number (which is 2 * integer limit) to get
'our new long integer.
IF IntNumber% < 0 THEN
Int2Long& = 65536 + IntNumber%
ELSE
Int2Long& = IntNumber%
END IF
END FUNCTION
FUNCTION PeekWord% (Segment%, Offset%)
DEF SEG = Segment% 'set segment
High = PEEK(Offset% + 1) 'High byte is at offset + 1
Low = PEEK(Offset%) 'Low byte is at offset
PeekWord% = (High * 256) + Low 'Compute the word value
DEF SEG 'return to default segment
END FUNCTION
SUB PokeWord (Segment%, Offset%, Word%)
DEF SEG = Segment% 'Set segment
High = (Word% \ 256) 'perform integer division
'to compute the high byte
Low = Word% - (High * 256) 'compute the low byte
POKE (Offset% + 1), High 'POKE in the high byte
POKE Offset%, Low 'POKE in the low byte
DEF SEG 'return to the default segment
END SUB